package com.ux.control
{
	
	import com.ux.event.PagingEvent;
	
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.text.TextDisplayMode;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFieldType;
	import flash.text.TextFormat;
	import flash.text.TextFormatAlign;
	
	[Event(name="selectPage", type="com.ux.event.PagingEvent")]
	[Event(name="nextPage", type="com.ux.event.PagingEvent")]
	[Event(name="prevPage", type="com.ux.event.PagingEvent")]
	[Event(name="nextBlock", type="com.ux.event.PagingEvent")]
	[Event(name="prevBlcok", type="com.ux.event.PagingEvent")]
	[Event(name="pageChange", type="com.ux.event.PagingEvent")]
	
	/**
	 * paging 처리 하는 Class
	 * @author winnie
	 */	
	public class Paging extends Sprite
	{
		
		
		// 전체 게시물 갯수
		private var _totalNum : int;
		
		// 하나의 블럭에 몇개 페이지를 보여줄 것인가.
		private var _numOfView : int;
		
		// 블럭 갯수 = _numOfView / _totalNum
		private var _blockNum : int;
		
		// 현재 페이지
		private var _nowPage : int;
		
		// 현재 블럭
		private var _nowBlock : int;
		
		
		//-------------- 블록 버튼들, 내부에 텍스트 필드를 가지고 있음 -----------------//
		
		// 다음블록 버튼 
		private var _nextBlockBtn : Sprite;
		
		// 이전블록 버튼
		private var _prevBlockBtn : Sprite;
		
		// 다음페이지 버튼
		private var _nextPageBtn : Sprite;
		
		// 이전 페이지 버튼
		private var _prevPageBtn : Sprite;
		
		//-------------- 블록 버튼들 끝 ---------------------------------------------//
		
		
		// 페이지 버튼 리스트
		private var _pageBtnList : Array		= [];
		
		// 선택된 페이지의 텍스트 포멧
		private var _nowPageTextFormat : TextFormat;
		
		// 선택되지 않은 페이지의 텍스트 포멧
		private var _otherPageTextFormat : TextFormat;
		
		// 버튼들 자간
		private var _intervalOfBtn : Number;
		
		// 오버 텍스트 컬러
		private var _overTextColor : uint = 0xff0000;
		
		// 디폴트 텍스트 컬러
		private var _defaultTextColor : uint = 0x666666;
		
		
		/**
		 * <br />
		 * Constructor<br />
		 * totalNum : 전체 게시물 갯수 < 기본값 : 1 ><br />
		 * numOfView : 하나의 블럭에 몇개 페이지를 보여줄 것인가 < 기본값 : 5 ><br />
		 * nowPage : 현재 페이지 < 기본값 : 1 ><br />
		 * 
		 * <br />
		 * // 사용 예제
		 * <br />
		 * 		var page : Paging = new Paging( 60,10,1 );<br />
		 * 		this.addChild( page );<br />
		 * 		<br />
		 * 		page.addEventListener(PagingEvent.PAGE_CHANGE, onPageChange );<br />
		 * 		<br /><br /><br />
		 * 		function onPageChange( e:PagingEvent ):void<br />
		 * 		{<br />
		 * 		trace( e.page );<br />
		 * 		}<br />
		 * 
		 * 
		 * 		//SELECT_PAGE, NEXT_PAGE, PREV_PAGE, NEXT_BLOCK, PREV_BLOCK 등의 이벤트가 더 있음.
		 */		
		public function Paging(totalNum:int = 50, numOfView:int = 8, nowPage:int = 1 )
		{
			super();
			
			this._totalNum			= totalNum;
			this._numOfView			= numOfView;
			this._nowPage			= nowPage;
			
			this._blockNum			= Math.ceil( this._totalNum / this._numOfView );
			this._nowBlock			= Math.ceil( this._nowPage / this._numOfView );
			
			this.makeBtn();
			
			this.setBtnEvent();
			
			this.addEventListener( Event.ADDED_TO_STAGE, onStage );
		}
		
		
		// stage 에 addChild 될때
		private function onStage( e:Event ):void
		{
			
			this.defaultSetting();
			this.initEvent();
			this.initLayout();
			
		}
		
		// ----------- defaultSetting ------------- //
		private function defaultSetting():void
		{
			
			
		}
		
		// ----------- initEvent ------------- //
		private function initEvent():void
		{
			
		}
		
		// ----------- initLayout ------------- //
		private function initLayout():void
		{
			
		}
		
		
		// 페이지 버튼을 클릭 했을 때
		private function onBtnClick( e:MouseEvent ):void
		{
			switch( e.currentTarget )
			{
				case this._prevBlockBtn : 	this.moveToPrevBlock(); break;
				case this._prevPageBtn : 	this.moveToPrevPage(); break;
				case this._nextPageBtn : 	this.moveToNextPage(); break;
				case this._nextBlockBtn : 	this.moveToNextBlock(); break;
				default : this.moveToSelectedPage( this._pageBtnList.indexOf( e.currentTarget ) ); break;
			}
		}
		
		
		private function setBtnEvent():void
		{
			this._prevBlockBtn.addEventListener(MouseEvent.CLICK, onBtnClick );
			this._prevBlockBtn.buttonMode		= true;
			this._prevPageBtn.addEventListener(MouseEvent.CLICK, onBtnClick );
			this._prevPageBtn.buttonMode		= true;
			
			var _len : int			= this._pageBtnList.length; 
			for( var i:int = 0; i<_len; i++ )
			{
				this._pageBtnList[ i ].addEventListener(MouseEvent.CLICK, onBtnClick );
				this._pageBtnList[ i ].buttonMode	= true;
			}
			
			this._nextPageBtn.addEventListener(MouseEvent.CLICK, onBtnClick );
			this._nextPageBtn.buttonMode		= true;
			this._nextBlockBtn.addEventListener(MouseEvent.CLICK, onBtnClick );
			this._nextBlockBtn.buttonMode		= true;
		}
		
		
		// PrevBlockBtn 클릭된 경우
		private function moveToPrevBlock():void
		{
			
			this._nowPage 		= 1;
			this._nowBlock		= 1;
			this.setBtns();
			
			dispatchEvent(new PagingEvent( PagingEvent.PREV_BLOCK, this._nowPage ) );
			dispatchEvent(new PagingEvent( PagingEvent.PAGE_CHANGE, this._nowPage ) );
			
		}
		
		// PrevPageBtn 클릭된 경우
		private function moveToPrevPage():void
		{
			
			if( this._nowBlock > 1 )
			{
				this._nowBlock--;
				this._nowPage		= (this._nowBlock-1)*this._numOfView + this._numOfView;
				this.setBtns();
				
				dispatchEvent(new PagingEvent( PagingEvent.PREV_PAGE, this._nowPage ) );
				dispatchEvent(new PagingEvent( PagingEvent.PAGE_CHANGE, this._nowPage ) );
			}
			
			
		}
		
		
		// NextPageBtn 클릭된 경우
		private function moveToNextPage():void
		{
			if( this._nowBlock < this._blockNum )
			{
				this._nowBlock++;
				this._nowPage		= (this._nowBlock-1)*this._numOfView + 1;
				this.setBtns();
				
				dispatchEvent(new PagingEvent( PagingEvent.NEXT_PAGE, this._nowPage ) );
				dispatchEvent(new PagingEvent( PagingEvent.PAGE_CHANGE, this._nowPage ) );
			}
		}
		
		// NextBlockBtn 클릭된 경우
		private function moveToNextBlock():void
		{
			this._nowPage 		= this._totalNum;
			this._nowBlock		= this._blockNum;
			this.setBtns();
			
			dispatchEvent(new PagingEvent( PagingEvent.NEXT_BLOCK, this._nowPage ) );
			dispatchEvent(new PagingEvent( PagingEvent.PAGE_CHANGE, this._nowPage ) );
		}
		
		// 특정 페이지 버튼이 클릭된 경우
		private function moveToSelectedPage( idx : int ):void
		{
			this._nowPage		= ( ( idx + 1 ) + ( ( this._nowBlock-1 ) * this._numOfView ) );
			this.setBtns();
			
			dispatchEvent(new PagingEvent( PagingEvent.SELECT_PAGE, this._nowPage ) );
			dispatchEvent(new PagingEvent( PagingEvent.PAGE_CHANGE, this._nowPage ) );
		}
		
		// 클릭 된 이후 버튼들 다시 셋팅
		private function setBtns():void
		{
			if( _prevPageBtn == null || _prevBlockBtn == null || _nextBlockBtn == null || _nextPageBtn == null )
			{
				this.makeBtn();
				return;
			}
			
			// 블럭 갯수 재조정
			this._blockNum			= Math.ceil( this._totalNum / this._numOfView );
			
			
			// 위치 재조정
			this._prevBlockBtn.x	= 0;
			this._prevPageBtn.x		= this._prevBlockBtn.width + this.getIntervalOfBtn;
			
			
			// 1,2,3,4,5 라면 start = 1, end = 5
			var startPage : int		= this._numOfView * this._nowBlock - this._numOfView + 1;
			var endPage : int		= Math.min( (startPage + this._numOfView), (this._totalNum+1) );
			
			// 만약  total 갯수보다 현재 뿌려지는 숫자가 더 커진다면... 그만큼 제거.. 
			// ex ) 50 까지인데  이번 페이지는 49, 50, 51, 52, 53, 54 .... 이렇게 간다면..  51부터 제거..
			if( endPage - startPage < this._pageBtnList.length )
			{
				for( var j:int = (endPage); j<(startPage + this._numOfView); j++ )
				{
					var overBtn : Sprite		= this._pageBtnList[ j - startPage ] as Sprite;
					
					if( overBtn && this.contains(overBtn) )
					{
						this.removeChild( overBtn );
					}
				}
			}
			
			
			// numOfView 갯수를 줄였을 때 남는 버튼 제거.
			if( this._pageBtnList.length > this._numOfView )
			{
				for( j = this._pageBtnList.length; j>this._numOfView; j-- )
				{
					
					this.removeChild( this._pageBtnList[ j-1 ] );
					this._pageBtnList.splice( j-1, 1 );
				}
			}
			
			
			// 실제 나올 버튼들 셋팅
			var lastBtn : Sprite;
			for( var i:int = startPage; i<endPage; i++ )
			{
				var btn : Sprite;
				
				if( ( i-startPage ) >= this._pageBtnList.length )
				{
					btn		= this.createBtn();
				}
				else
				{
					btn		= this._pageBtnList[ i-startPage ] as Sprite;
				}
				
				if( btn && !this.contains(btn) )
				{
					this.addChild( btn );
				}
				
				btn.addEventListener(MouseEvent.CLICK, onBtnClick );
				btn.buttonMode	= true;
				
				var label : TextField	= btn.getChildAt( 0 ) as TextField;
				label.text		= String( i );
				
				if( i == startPage )
				{
					btn.x	= this._prevPageBtn.width + this._prevPageBtn.x + this.getIntervalOfBtn;
					
					if( i == this._nowPage )
					{
						label.setTextFormat( this.nowPageTextFormat );
					}
					else
					{
						label.setTextFormat( this.otherPageTextFormat );
					}
				}
				else
				{
					btn.x	= _pageBtnList[i-startPage-1].width + _pageBtnList[i-startPage-1].x + this.getIntervalOfBtn;
					
					if( i == this._nowPage )
					{
						label.setTextFormat( this.nowPageTextFormat );
					}
					else
					{
						label.setTextFormat( this.otherPageTextFormat );
					}
				}
				
				lastBtn		= btn;
			}
			
			// 오른쪽 버튼들 위치 재조정
			this._nextPageBtn.x		= lastBtn.x + lastBtn.width + this.getIntervalOfBtn;
			this._nextBlockBtn.x		= this._nextPageBtn.x + this._nextPageBtn.width + this.getIntervalOfBtn;
			
			
		}
		
		
		private function makeBtn():void
		{
			// ◀◀ 버튼
			if( _prevBlockBtn == null )
			{
				this._prevBlockBtn		= new Sprite();
//				var prevBlockLabel : TextField	= this.makeTextField("◀◀", this.otherPageTextFormat );
//				prevBlockLabel.setTextFormat( this.otherPageTextFormat );
//				this._prevBlockBtn.addChild( prevBlockLabel );
				this.addChild( this._prevBlockBtn );
			}
			
			// ◀ 버튼
			if( _prevPageBtn == null )
			{
				this._prevPageBtn		= new Sprite();
				var prevPageLabel : TextField	= this.makeTextField("◀", this.otherPageTextFormat );
				prevPageLabel.setTextFormat( this.otherPageTextFormat );
				this._prevPageBtn.addChild( prevPageLabel );
				this.addChild( this._prevPageBtn );
			}
			
			// ▶버튼
			if( _nextPageBtn == null )
			{
				this._nextPageBtn		= new Sprite();
				var nextPageLabel : TextField	= this.makeTextField("▶", this.otherPageTextFormat );
				this._nextPageBtn.addChild( nextPageLabel );
				this.addChild( this._nextPageBtn );
			}
			
			// ▶ ▶버튼
			if( _nextBlockBtn == null )
			{
				this._nextBlockBtn		= new Sprite();
//				var nextBlockLabel : TextField	= this.makeTextField("▶▶", this.otherPageTextFormat );
//				this._nextBlockBtn.addChild( nextBlockLabel );
				this.addChild( this._nextBlockBtn );
			}
			
			// 1,2,3,4,5 버튼들 생성
			this.setBtns();
		}
		
		
		private function createBtn():Sprite
		{
			var btn : Sprite	= new Sprite();
			var label : TextField	= new TextField();
			label.multiline		= false;
			label.mouseEnabled	= false;
			label.autoSize		= TextFieldAutoSize.LEFT;
			
			btn.addChild( label );
			this.addChild( btn );
			this._pageBtnList.push( btn );
			
			return btn;
		}
		
		
		// 텍스트 필드 생성
		private function makeTextField( txt : String, format : TextFormat ):TextField
		{
			var tf : TextField	= new TextField();
			tf.text			= txt;
			tf.autoSize		= TextFieldAutoSize.LEFT;
			tf.multiline		= false;
			tf.mouseEnabled		= false;
			tf.setTextFormat( format );
			return tf;
		}
		
		// 버튼에 스킨을 등록하기 위해 기존의 스킨을 제거하는 메서드
		private function resetSkin( _target : Sprite, _skin:DisplayObject ):void
		{
			if( _target.numChildren > 0 )
			{
				var _len : int		= _target.numChildren;
				for( var i:int = 0; i<_len; i++ )
				{
					_target.removeChildAt( 0 );
				}
			}
			
			_target.addChild( _skin );
		}
		
		
		
		
		
		
		
		//-------------------------------------- setter , getter ---------------------------------------//
		//-------------------------------------- setter , getter ---------------------------------------//
		//-------------------------------------- setter , getter ---------------------------------------//
		//-------------------------------------- setter , getter ---------------------------------------//
		//-------------------------------------- setter , getter ---------------------------------------//
		
		
		
		
		
		
		
		/**
		 * pageNum 을 바꾼 후 버튼들 리셋팅 할 때 호출하는 메서드
		 */		
		public function resetPage():void
		{
			this.setBtns();
		}
		
		/**
		 * <br />
		 * 전체 게시물 갯수
		 */			
		public function set setTotalNum( totalNum:int ):void
		{
			this._totalNum		= totalNum;
			this.resetPage();
		}
		
		/**
		 * <br />
		 * 하나의 블럭에 몇개 페이지를 보여줄 것인가
		 */			
		public function set setNumOfView( numOfView:int ):void
		{
			this._numOfView		= numOfView;
			this.resetPage();
		}
		
		/**
		 * <br />
		 * 현재 페이지
		 */			
		public function set setNowPage( nowPage:int ):void
		{
			this._nowPage		= nowPage;
			this._nowBlock		= Math.ceil( this._nowPage / this._numOfView );
			this.resetPage();
		}
		
		/**
		 * <br />
		 * 버튼 사이 간격
		 */		
		public function set setIntervalOfBtn( interval : Number ):void
		{
			this._intervalOfBtn		= interval;
			resetPage();
		}
		
		/**
		 * 이전 페이지 스킨을 등록하는 setter
		 */		
		public function set setSkinPrevPage( _skin:DisplayObject ):void
		{
			this.resetSkin( this._prevPageBtn,  _skin );
			resetPage();
		}
		
		/**
		 * 이전 블록  스킨을 등록하는 setter
		 */
		public function set setSkinPrevBlock( _skin:DisplayObject ):void
		{
			this.resetSkin( this._prevBlockBtn,  _skin );
			resetPage();
		}
		
		/**
		 * 다음 페이지 스킨을 등록하는 setter
		 */		
		public function set setSkinNextPage( _skin:DisplayObject ):void
		{
			this.resetSkin( this._nextPageBtn,  _skin );
			resetPage();
		}
		
		/**
		 * 다음 블록  스킨을 등록하는 setter
		 */
		public function set setSkinNextBlock( _skin:DisplayObject ):void
		{
			this.resetSkin( this._nextBlockBtn,  _skin );
			resetPage();
		}
		
		
		/**
		 * 현재 페이지가 아닌 버튼들의 텍스트 포멧 setter
		 */		
		public function set otherPageTextFormat(_format : TextFormat):void
		{
			this._otherPageTextFormat		= _format;
		}
		
		/**
		 * 현재 페이지인 버튼의 텍스트 포멧 setter
		 */		
		public function set nowPageTextFormat(_format : TextFormat):void
		{
			this._nowPageTextFormat			= _format;
		}
		
		
		/**
		 * 현재 페에지인 숫자의 컬러 
		 */
		public function set overTextColor( color : uint ):void
		{
			this._overTextColor = color;
			resetPage();
		}
		
		/**
		 * 기본 텍스트 컬러 
		 */
		public function set defaultTextColor( color : uint ):void
		{
			this._defaultTextColor = color;
			resetPage();
		}
		
		/**
		 * <br />
		 * 버튼 사이 간격 리턴
		 */		
		public function get getIntervalOfBtn():Number
		{
			if( !this._intervalOfBtn )
			{
				this._intervalOfBtn	= 9;
			}
			
			return this._intervalOfBtn;
		}
		
		/**
		 * 현재 페이지가 아닌 버튼들의 텍스트 포멧 getter
		 */		
		public function get otherPageTextFormat():TextFormat
		{
			if( this._otherPageTextFormat == null )
			{
				this._otherPageTextFormat		= new TextFormat("돋움",11,defaultTextColor,false );
			}
			
			return this._otherPageTextFormat;
		}
		
		/**
		 * 현재 페이지인 버튼의 텍스트 포멧 getter
		 */		
		public function get nowPageTextFormat():TextFormat
		{
			if( this._nowPageTextFormat == null )
			{
				this._nowPageTextFormat			= new TextFormat("돋움",11,overTextColor,true );
			}
			
			return this._nowPageTextFormat;
		}
		
		/**
		 * 현재 페에지인 숫자의 컬러 
		 */
		public function get overTextColor():uint
		{
			return this._overTextColor;
		}
		
		/**
		 * 기본 텍스트 컬러 
		 */
		public function get defaultTextColor():uint
		{
			return this._defaultTextColor;
		}
	}
}







